package cn.woowc.through.thread;

import cn.woowc.through.listener.event.ThroughNatLogInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

/**
 * @version V0.0.1
 * @ClassName: {@link NotifyUrlRunnable}
 * @Description: NotifyUrlRunnable
 * @author: Lanzhou
 * @date: 2021/5/2 15:31
 * @Copyright:2019 All rights reserved.
 * 注意：本内容仅限于本人开发与维护，禁止外泄以及用于其他的商业目
 */
@Slf4j
public class NotifyUrlRunnable implements Runnable {

    /**
     * 代理地址
     */
    private static final String HTTP_PREFIX = "http://";

    /**
     * 后缀
     */
    private static final String NAT_SUFFIX = "natappfree.cc";

    private String path;

    private String className;

    public NotifyUrlRunnable(String path, String className) {
        this.path = path;
        this.className = className;
    }

    @Override
    public void run() {
        String domain = this.path;
        // 同步获取有网址信息的数据
        if (className.equals(ThroughNatLogInfo.class.getName())) {
            domain = asyncGetUrl();
        }
        log.info("您的服务已经启动完成, 此次[公网]可访问地址为: {}{}", HTTP_PREFIX, domain);
    }


    /**
     * 阻塞获取地址
     *
     * @return
     */
    private String asyncGetUrl() {
        String fileInfo = "";
        do {
            fileInfo = readLog(path);
            try {
                Thread.sleep(200);
                log.info("200ms 后获取下次的文件信息");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // 当数据内有预期值(前后缀都有)了, 就认为他可以了
            if (fileInfo.contains(HTTP_PREFIX) && fileInfo.contains(NAT_SUFFIX)) {
                break;
            }
        } while (!fileInfo.contains(HTTP_PREFIX) || !fileInfo.contains(NAT_SUFFIX));
        log.debug("获取日志数据为: [ {} ]", fileInfo);
        // 变成行数据
        String[] rows = fileInfo.split("\n");
        String target = null;
        for (String row : rows) {
            if (row.contains(HTTP_PREFIX) && row.contains(NAT_SUFFIX)) {
                String[] dataArr = row.split(HTTP_PREFIX);
                target = dataArr[dataArr.length - 1];
            }
        }
        if (StringUtils.isBlank(target)) {
            log.warn("获取远程数据失败, 请稍后重试");
        }
        log.info("当前的链接地址变换为: [ {} ]", target);
        return target;
    }

    /**
     * 读取日志信心, 读取出错会返回FAIL
     *
     * @param path
     * @return
     */
    private String readLog(String path) {
        FileInputStream fileInputStream = null;
        try {
            fileInputStream = new FileInputStream(path);
            StringBuilder sb = new StringBuilder();
            FileChannel channel = fileInputStream.getChannel();
            ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
            while (channel.read(byteBuffer) != -1) {
                // 先反转, 变成输出缓冲流, 然后在清空
                byteBuffer.flip();
                byte[] array = byteBuffer.array();
                String temp = new String(array);
                sb.append(temp);
                byteBuffer.clear();
            }
            return sb.toString();
        } catch (IOException e) {
            log.debug("获取文件内容失败, 检查相关信息 [ {} ]", e.getMessage());
            return "FAIL";
        }
    }


    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }

}
